package de.streblow.justscan;

import java.io.IOException;
import android.util.AttributeSet;
//import java.util.List;
import android.view.Surface;
import android.view.SurfaceView;
import android.view.SurfaceHolder;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.AutoFocusCallback;

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {

	private SurfaceHolder mHolder;
	private Camera mCamera;
	private PreviewCallback previewCallback;
	private AutoFocusCallback autoFocusCallback;
	private Activity mActivity;
	public int mScanAreaColor;
	public int mScanAreaWidth;
	public int mScanAreaHeight;
	public int mScanAreaEdgelet;

	public CameraPreview(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public CameraPreview(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public CameraPreview(Context context) {
		super(context);
	}

	@SuppressWarnings("deprecation")
	public CameraPreview(Context context, Camera camera,
		PreviewCallback previewCb, AutoFocusCallback autoFocusCb,
		int areaColor, int areaWidth, int areaHeight, int areaEdgelet) {
		super(context);
		mCamera = camera;
		previewCallback = previewCb;
		autoFocusCallback = autoFocusCb;
		mActivity = (Activity)context;
		mScanAreaColor = areaColor;
		mScanAreaWidth = areaWidth;
		mScanAreaHeight = areaHeight;
		mScanAreaEdgelet = areaEdgelet;

//		//Set camera to continuous focus if supported, otherwise use
//		//software auto-focus. Only works for API level >=9.
//		Camera.Parameters parameters = mCamera.getParameters();
//		List<String> focusmodes = parameters.getSupportedFocusModes();
//		if (focusmodes.contains(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE))
//			parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
//		mCamera.setParameters(parameters);

		//Install a SurfaceHolder.Callback so we get notified when the
		//underlying surface is created and destroyed.
		mHolder = getHolder();
		mHolder.addCallback(this);

//		//deprecated setting, but required on Android versions prior to 3.0
		if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) {
			mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		}
	}

	public void surfaceCreated(SurfaceHolder holder) {
		setWillNotDraw(false);
		// The Surface has been created, now tell the camera where to draw the preview.
		try {
			mCamera.setPreviewDisplay(holder);
			mCamera.setPreviewCallback(new PreviewCallback() {
				public void onPreviewFrame(byte[] data, Camera cam) {
					setInvalidate();
				}
			});
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void setInvalidate() {
		invalidate();
	}

	public void surfaceDestroyed(SurfaceHolder holder) {
		//Camera preview released in activity
		holder.removeCallback(this);
	}

	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
		//If your preview can change or rotate, take care of those events here.
		//Make sure to stop the preview before resizing or reformatting it.
		if (mHolder.getSurface() == null){
			//preview surface does not exist
			return;
		}

		//stop preview before making changes
		try {
			mCamera.stopPreview();
		} catch (Exception e){
			//ignore: tried to stop a non-existent preview
		}

		try {
			setCameraDisplayOrientation(mActivity, Camera.CameraInfo.CAMERA_FACING_BACK, mCamera);
			mCamera.setPreviewDisplay(mHolder);
			mCamera.setPreviewCallback(previewCallback);
			mCamera.startPreview();
			mCamera.autoFocus(autoFocusCallback);
		} catch (Exception e){
			e.printStackTrace();
		}
	}

	public static void setCameraDisplayOrientation(Activity activity,
		int cameraId, android.hardware.Camera camera) {
		int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
		int degrees = 0;
		switch (rotation) {
			case Surface.ROTATION_0: degrees = 0; break;
			case Surface.ROTATION_90: degrees = 90; break;
			case Surface.ROTATION_180: degrees = 180; break;
			case Surface.ROTATION_270: degrees = 270; break;
		}
		int result;
		android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
		android.hardware.Camera.getCameraInfo(cameraId, info);
		if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
			result = (info.orientation + degrees) % 360;
			result = (360 - result) % 360;  // compensate the mirror
		} else {
			// back-facing
			result = (info.orientation - degrees + 360) % 360;
		}
		camera.setDisplayOrientation(result);
	}

	@Override
	public void draw(Canvas canvas) {
		super.draw(canvas);
		int areaWidth = mScanAreaWidth * getWidth() / 100;
		int areaHeight = mScanAreaHeight * getHeight() / 100;
		int areaEdgelet = mScanAreaEdgelet * areaHeight / 100;
		Paint p = new Paint();
		p.setColor(mScanAreaColor);
		p.setStyle(Style.STROKE);
		p.setStrokeWidth(0);
//		canvas.drawRect((getWidth() - areaWidth) / 2, (getHeight() - areaHeight) / 2, (getWidth() - areaWidth) / 2 + areaWidth - 1, (getHeight() - areaHeight) / 2 + areaHeight - 1, p);
		canvas.drawLine((getWidth() - areaWidth) / 2, (getHeight() - areaHeight) / 2 + areaEdgelet, (getWidth() - areaWidth) / 2, (getHeight() - areaHeight) / 2, p);
		canvas.drawLine((getWidth() - areaWidth) / 2, (getHeight() - areaHeight) / 2, (getWidth() - areaWidth) / 2 + areaWidth - 1, (getHeight() - areaHeight) / 2, p);
		canvas.drawLine((getWidth() - areaWidth) / 2 + areaWidth - 1, (getHeight() - areaHeight) / 2, (getWidth() - areaWidth) / 2 + areaWidth - 1, (getHeight() - areaHeight) / 2 + areaEdgelet, p);
		canvas.drawLine((getWidth() - areaWidth) / 2, (getHeight() - areaHeight) / 2 + areaHeight - 1 - areaEdgelet, (getWidth() - areaWidth) / 2, (getHeight() - areaHeight) / 2 + areaHeight - 1, p);
		canvas.drawLine((getWidth() - areaWidth) / 2, (getHeight() - areaHeight) / 2 + areaHeight - 1, (getWidth() - areaWidth) / 2 + areaWidth - 1, (getHeight() - areaHeight) / 2 + areaHeight - 1, p);
		canvas.drawLine((getWidth() - areaWidth) / 2 + areaWidth - 1, (getHeight() - areaHeight) / 2 + areaHeight, (getWidth() - areaWidth) / 2 + areaWidth - 1, (getHeight() - areaHeight) / 2 + areaHeight -1 - areaEdgelet, p);
	}
}
